#include "TcpServer.h"
#include "TcpConnection.h"
#include "Channel.h"
// #include "Log/Logging.h"
#include "Socket.h"
#include "EventLoop.h"
#include "EventLoopThreadPool.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>  // snprintf
#include <memory>
#include "util.h"

using namespace std::placeholders;

// std::map<std::thread::id, std::shared_ptr<std::mutex>> readLockMap_;

void defalutTimercallback() {

}

TcpServer::TcpServer(EventLoop* loop, int port)
	: loop_(loop),
	threadPool_(new EventLoopThreadPool(loop)),
	name_("connection"),
	listenSocket_( new Socket(createNonblockingSocket())),
	started_(false),
	nextConnId_(0),
	port_(port)
{
	listenSocket_->bindAddress(port_);
	listenSocket_->setReuseAddr(true);
	listenSocket_->setKeepAlive(true);
	acceptor_ = std::make_shared<Channel>(loop, listenSocket_->fd());
	acceptor_->setReadCallback(std::bind(&TcpServer::handleNewConnection, this));
	acceptor_->enableReading();
}

TcpServer::~TcpServer() {

}

void TcpServer::setThreadNum(int numThreads)
{
	assert(0 <= numThreads);
	threadPool_->setThreadNum(numThreads);
}

void TcpServer::start() {
	// 启动线程池
	threadPool_->start();
	// 创建监听套接字 开始监听
	std::cout << "listening" << std::endl;
	listenSocket_->listening();

}

void TcpServer::newConnection(int sockfd) {
	// 从池中取出一个EventLoop
	EventLoop* ioLoop = threadPool_->getNextLoop();
	ioLoop->runInLoop(std::bind(&EventLoop::newConnection, ioLoop, sockfd, connectionCallback_, messageCallback_));
}

void TcpServer::removeConnection(const TcpConnectionPtr& conn) {
	loop_->runInLoop(std::bind(&TcpServer::removeConnectionInLoop, this, conn));
}

void TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
{
	loop_->assertInLoopThread();
	size_t n = connections_.erase(conn->name());
	EventLoop* ioLoop = conn->getLoop();
	ioLoop->queueInLoop(std::bind(&TcpConnection::connectDestroyed, conn));
}

// 调用accept
// 可以修改为循环accept直到没有新连接 适合短连接服务
void TcpServer::handleNewConnection() {
    loop_->assertInLoopThread();
	while (1) {
		int connfd = listenSocket_->accept();
		if (connfd > 0) {
			if (connfd > 4000) {
				close(connfd);
				continue;
			}
			newConnection(connfd);
		} 
		else {
			break;
		}
	}
}

